From 1d95a6efa9a595460474bac537a554ecbedb341e Mon Sep 17 00:00:00 2001 From: Andrew Garrett Date: Fri, 12 Jan 2007 07:31:34 +0000 Subject: [PATCH] Display MULTIPLE culprit pages for cascading protection in the messages. Also improve performance by separating boolean 'is this page affected by a cascading protection' from array 'who are the culprits for this cascading protection' -- both are cached in member variables of the Title object. --- includes/EditPage.php | 13 ++-- includes/OutputPage.php | 13 ++-- includes/ProtectionForm.php | 13 ++-- includes/Title.php | 108 ++++++++++++++++++------------ languages/messages/MessagesEn.php | 9 ++- 5 files changed, 97 insertions(+), 59 deletions(-) diff --git a/includes/EditPage.php b/includes/EditPage.php index cd0fee48cd..4e8dd9106c 100644 --- a/includes/EditPage.php +++ b/includes/EditPage.php @@ -962,7 +962,7 @@ class EditPage { } } - $cascadeSource = $this->mTitle->getCascadeProtectionSource(); + $cascadeSources = $this->mTitle->getCascadeProtectionSources(); if( $this->mTitle->isProtected( 'edit' ) ) { # Is the protection due to the namespace, e.g. interface text? @@ -975,12 +975,15 @@ class EditPage { if( wfEmptyMsg( 'semiprotectedpagewarning', $notice ) || $notice == '-' ) { $notice = ''; } - } elseif ($cascadeSource) { + } elseif (count($cascadeSources) > 0) { # Cascaded protection: warn the user. - $cascadeSourceTitle = Title::newFromId($cascadeSource); - $cascadeSourceText = $cascadeSourceTitle->getPrefixedText(); + $titles = ''; + + foreach ( $cascadeSources as $title ) { + $titles .= '* ' . $title->getPrefixedText() . "\r\n"; + } - $notice = wfMsgForContent( 'cascadeprotectedwarning', $cascadeSourceText ); + $notice = wfMsgForContent( 'cascadeprotectedwarning', $titles ); } else { # No; regular protection $notice = wfMsg( 'protectedpagewarning' ); diff --git a/includes/OutputPage.php b/includes/OutputPage.php index 6668336f3d..168332b582 100644 --- a/includes/OutputPage.php +++ b/includes/OutputPage.php @@ -893,17 +893,20 @@ class OutputPage { $this->setPageTitle( wfMsg( 'viewsource' ) ); $this->setSubtitle( wfMsg( 'viewsourcefor', $skin->makeKnownLinkObj( $wgTitle ) ) ); - $cascadeSource = $wgTitle->getCascadeProtectionSource(); + $cascadeSources = $wgTitle->getCascadeProtectionSources(); # Determine if protection is due to the page being a system message # and show an appropriate explanation if( $wgTitle->getNamespace() == NS_MEDIAWIKI ) { $this->addWikiText( wfMsg( 'protectedinterface' ) ); - } if ( $cascadeSource ) { - $cascadeSourceTitle = Title::newFromId( $cascadeSource ); - $cascadeSourceText = $cascadeSourceTitle->getPrefixedText(); + } if ( count($cascadeSources) ) { + $titles = ''; + + foreach ( $cascadeSources as $title ) { + $titles .= '* ' . $title->getPrefixedText() . "\r\n"; + } - $this->addWikiText( wfMsgForContent( 'cascadeprotected', $cascadeSourceText ) ); + $this->addWikiText( wfMsgForContent( 'cascadeprotected', $titles ) ); } else { $this->addWikiText( wfMsg( 'protectedpagetext' ) ); } diff --git a/includes/ProtectionForm.php b/includes/ProtectionForm.php index e83c38b580..f333db5e11 100644 --- a/includes/ProtectionForm.php +++ b/includes/ProtectionForm.php @@ -73,13 +73,16 @@ class ProtectionForm { return; } - $cascadeSource = $this->mTitle->getCascadeProtectionSource(); + $cascadeSources = $this->mTitle->getCascadeProtectionSources(); - if ( $cascadeSource ) { - $cascadeSourceTitle = Title::newFromId( $cascadeSource ); - $cascadeSourceText = $cascadeSourceTitle->getPrefixedText(); + if ( count($cascadeSources) > 0 ) { + $titles = ''; - $wgOut->addWikiText( wfMsgForContent( 'protect-cascadeon', $cascadeSourceText ) ); + foreach ( $cascadeSources as $title ) { + $titles .= '* ' . $title->getPrefixedText() . "\r\n"; + } + + $wgOut->addWikiText( wfMsgForContent( 'protect-cascadeon', $titles ) ); } if( $this->save() ) { diff --git a/includes/Title.php b/includes/Title.php index b58739b2be..d206bd098a 100644 --- a/includes/Title.php +++ b/includes/Title.php @@ -44,23 +44,23 @@ class Title { * @private */ - var $mTextform; # Text form (spaces not underscores) of the main part - var $mUrlform; # URL-encoded form of the main part - var $mDbkeyform; # Main part with underscores - var $mNamespace; # Namespace index, i.e. one of the NS_xxxx constants - var $mInterwiki; # Interwiki prefix (or null string) - var $mFragment; # Title fragment (i.e. the bit after the #) - var $mArticleID; # Article ID, fetched from the link cache on demand - var $mLatestID; # ID of most recent revision - var $mRestrictions; # Array of groups allowed to edit this article - var $mCascadeRestriction; - var $mCascadeRestrictionSource; - var $mRestrictionsLoaded; # Boolean for initialisation on demand - var $mPrefixedText; # Text form including namespace/interwiki, initialised on demand - var $mDefaultNamespace; # Namespace index when there is no namespace - # Zero except in {{transclusion}} tags - var $mWatched; # Is $wgUser watching this page? NULL if unfilled, accessed through userIsWatching() - var $mOldRestrictions; # Is the page using old-fashioned page_restrictions column? + var $mTextform; # Text form (spaces not underscores) of the main part + var $mUrlform; # URL-encoded form of the main part + var $mDbkeyform; # Main part with underscores + var $mNamespace; # Namespace index, i.e. one of the NS_xxxx constants + var $mInterwiki; # Interwiki prefix (or null string) + var $mFragment; # Title fragment (i.e. the bit after the #) + var $mArticleID; # Article ID, fetched from the link cache on demand + var $mLatestID; # ID of most recent revision + var $mRestrictions; # Array of groups allowed to edit this article + var $mCascadeRestriction; # Cascade restrictions on this page to included templates and images? + var $mHasCascadingRestrictions; # Are cascading restrictions in effect on this page? + var $mCascadeRestrictionSources;# Where are the cascading restrictions coming from on this page? + var $mRestrictionsLoaded; # Boolean for initialisation on demand + var $mPrefixedText; # Text form including namespace/interwiki, initialised on demand + var $mDefaultNamespace; # Namespace index when there is no namespace + # Zero except in {{transclusion}} tags + var $mWatched; # Is $wgUser watching this page? NULL if unfilled, accessed through userIsWatching() /**#@-*/ @@ -1036,7 +1036,7 @@ class Title { if ( NS_SPECIAL == $this->mNamespace ) { return true; } - if ( $this->getCascadeProtectionSource() ) { return true; } + if ( $this->isCascadeProtected() ) { return true; } if( $action == 'edit' || $action == '' ) { $r = $this->getRestrictions( 'edit' ); @@ -1127,7 +1127,7 @@ class Title { return false; } - if ( $this->getCascadeProtectionSource() ) { + if ( $this->isCascadeProtected() ) { # We /could/ use the protection level on the source page, but it's fairly ugly # as we have to establish a precedence hierarchy for pages included by multiple # cascade-protected pages. So just restrict it to people with 'protect' permission, @@ -1330,38 +1330,53 @@ class Title { return ( $wgUser->isAllowed('editinterface') or preg_match('/^'.preg_quote($wgUser->getName(), '/').'\//', $this->mTextform) ); } + /** + * Cascading protection: Return true if cascading restrictions apply to this page, false if not. + * + * @return bool If the page is subject to cascading restrictions. + * @access public. + */ + function isCascadeProtected() { + return ( $this->getCascadeProtectionSources( false ) ); + } + /** * Cascading protection: Get the source of any cascading restrictions on this page. * - * @return int The page_id of the page from which cascading restrictions have come, or false for none. + * @param $get_pages bool Whether or not to retrieve the actual pages that the restrictions have come from. + * @return mixed Array of the Title objects of the pages from which cascading restrictions have come, false for none, or true if such restrictions exist, but $get_pages was not set. * @access public */ - function getCascadeProtectionSource() { + function getCascadeProtectionSources( $get_pages = true ) { - if ( isset( $this->mCascadeSource ) ) { - return $this->mCascadeSource; + if ( isset( $this->mCascadeSources ) && $get_pages ) { + return $this->mCascadeSources; + } else if ( isset( $this->mHasCascadingRestrictions ) && !$get_pages ) { + return $this->mHasCascadingRestrictions; } - $source = NULL; + $sources = NULL; if ( $this->getNamespace() == NS_IMAGE ) { - $source = $this->getCascadeProtectedImageSource(); + $sources = $this->getCascadeProtectedImageSources( $get_pages ); } else { - $source = $this->getCascadeProtectedPageSource(); + $sources = $this->getCascadeProtectedPageSources( $get_pages ); } - $this->mCascadeSource = $source; + if ( $get_pages ) { $this->mCascadeSources = $sources; } + else { $this->mHasCascadingRestrictions = $sources; } - return $source; + return $sources; } /** * Cascading protects: Check if the current image is protected due to a cascading restriction * - * @return int The page_id of the page from which cascading restrictions have come, or false for none. + * @param $get_pages bool Whether or not to retrieve the actual pages that the restrictions have come from. + * @return mixed Array of the Title objects of the pages from which cascading restrictions have come, false for none, or true if such restrictions exist, but $get_pages was not set. * @access public */ - function getCascadeProtectedImageSource() { + function getCascadeProtectedImageSources( $get_pages = true ) { global $wgEnableCascadingProtection; if (!$wgEnableCascadingProtection) return false; @@ -1370,17 +1385,22 @@ class Title { $dbr =& wfGetDb( DB_SLAVE ); - $cols = array( 'pr_page' ); + $cols = $get_pages ? array('pr_page') : array( 'il_to' ); $tables = array ('imagelinks', 'page_restrictions'); $where_clauses = array( 'il_to' => $this->getDBkey(), 'il_from=pr_page', 'pr_cascade' => 1 ); $res = $dbr->select( $tables, $cols, $where_clauses, __METHOD__); - if ($dbr->numRows($res)) { - $row = $dbr->fetchObject($res); - $culprit = $row->pr_page; + if ( $dbr->numRows($res) ) { + if ($get_pages) { + $culprits = array (); + while ($row = $dbr->fetchObject($res)) { + $page_id = $row->pr_page; + $culprits[$page_id] = Title::newFromId($page_id); + } + } else { return true; } wfProfileOut(__METHOD__); - return $culprit; + return $culprits; } else { wfProfileOut(__METHOD__); return false; @@ -1390,10 +1410,11 @@ class Title { /** * Cascading protects: Check if the current page is protected due to a cascading restriction. * - * @return int The page_id of the page from which cascading restrictions have come, or false for none. + * @param $get_pages bool Whether or not to retrieve the actual pages that the restrictions have come from. + * @return mixed Array of the Title objects of the pages from which cascading restrictions have come, false for none, or true if such restrictions exist, but $get_pages was not set. * @access public */ - function getCascadeProtectedPageSource() { + function getCascadeProtectedPageSources( $get_pages = true ) { global $wgEnableCascadingProtection; if (!$wgEnableCascadingProtection) return false; @@ -1402,17 +1423,22 @@ class Title { $dbr =& wfGetDb( DB_SLAVE ); - $cols = array( 'pr_page' ); + $cols = $get_pages ? array( 'pr_page' ) : array( 'tl_title' ); $tables = array ('templatelinks', 'page_restrictions'); $where_clauses = array( 'tl_namespace' => $this->getNamespace(), 'tl_title' => $this->getDBkey(), 'tl_from=pr_page', 'pr_cascade' => 1 ); $res = $dbr->select( $tables, $cols, $where_clauses, __METHOD__); if ($dbr->numRows($res)) { - $row = $dbr->fetchObject($res); - $culprit = $row->pr_page; + if ($get_pages) { + $culprits = array (); + while ($row = $dbr->fetchObject($res)) { + $page_id = $row->pr_page; + $culprits[$page_id] = Title::newFromId($page_id); + } + } else { return true; } wfProfileOut(__METHOD__); - return $culprit; + return $culprits; } else { wfProfileOut(__METHOD__); return false; diff --git a/languages/messages/MessagesEn.php b/languages/messages/MessagesEn.php index 5dc885bdc7..b2cddeb121 100644 --- a/languages/messages/MessagesEn.php +++ b/languages/messages/MessagesEn.php @@ -780,7 +780,8 @@ Query: $2', 'protectedinterface' => 'This page provides interface text for the software, and is locked to prevent abuse.', 'editinginterface' => "'''Warning:''' You are editing a page which is used to provide interface text for the software. Changes to this page will affect the appearance of the user interface for other users.", 'sqlhidden' => '(SQL query hidden)', -'cascadeprotected' => 'This page has been protected from editing, because it is included in [[$1]], which has been protected with the "cascading" option turned on.', +'cascadeprotected' => 'This page has been protected from editing, because it is included in the following pages, which are protected with the "cascading" option turned on: +$1', # Login and logout pages # @@ -1015,7 +1016,8 @@ so you will not be able to save your edits right now. You may wish to cut-n-past the text into a text file and save it for later.', 'protectedpagewarning' => "WARNING: This page has been locked so that only users with sysop privileges can edit it.", 'semiprotectedpagewarning' => "'''Note:''' This page has been locked so that only registered users can edit it.", -'cascadeprotectedwarning' => "WARNING: This page has been locked so that only users with sysop privileges can edit it, because it is included on [[$1]], which is protected with the 'cascading protection' option turned on.", +'cascadeprotectedwarning' => "WARNING: This page has been locked so that only users with sysop privileges can edit it, because it is included in the following pages, which are protected with the 'cascading protection' option turned on.: +$1", 'templatesused' => 'Templates used on this page:', 'templatesusedpreview' => 'Templates used in this preview:', 'templatesusedsection' => 'Templates used in this section:', @@ -1745,7 +1747,8 @@ Please hit "back" and reload the page you came from, then try again.', 'protect-text' => 'You may view and change the protection level here for the page $1.', 'protect-viewtext' => 'Your account does not have permission to change page protection levels. Here are the current settings for the page $1:', -'protect-cascadeon' => 'This page is currently subject to cascading protection, because it is included in [[$1]], which has been protected with the "cascading protection" option turned on. You can change the protection level for this page here, but it will not affect the cascading protection.', +'protect-cascadeon' => 'This page is currently subject to cascading protection, because it is included in the following pages, which are protected with the "cascading protection" option turned on. You can change the protection level for this page here, but it will not affect the cascading protection: +$1', 'protect-default' => '(default)', 'protect-level-autoconfirmed' => 'Block unregistered users', 'protect-level-sysop' => 'Sysops only', -- 2.20.1